/*
    Copyright (C) 2009-2011 Modelon AB

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


package TearingTests

model Test1
  Real u0,u1,u2,u3,uL;
  Real i0,i1,i2,i3,iL;
  parameter Real R1 = 1;
  parameter Real R2 = 1;
  parameter Real R3 = 1;
  parameter Real L = 1;
equation
  u0 = sin(time);
  u1 = R1*i1;
  u2 = R2*i2;
  u3 = R3*i3;
  uL = L*der(iL);
  u0 = u1 + u3;
  uL = u1 + u2;
  u2 = u3;
  i0 = i1 + iL;
  i1 = i2 + i3;

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="Test1",
			description="Test of tearing",
			equation_sorting=true,
			automatic_tearing=true,
			methodName="printDAEBLT",
			methodResult="
-------------------------------
Solved block of 1 variables:
Computed variable:
  u0
Solution:
  sin(time)
-------------------------------
Torn linear block of 2 iteration variables and 3 solved variables:
Coefficient variability: Parameter
Solved variables:
  i1
  u1
  u2
Iteration variables:
  i2
  i3
Solved equations:
  i1 = i2 + i3
  u1 = R1 * i1
  u0 = u1 + u2
Residual equations:
 Iteration variables: i2
  u2 = R3 * i3
 Iteration variables: i3
  u2 = R2 * i2
Jacobian:
  |1.0, 0.0, 0.0, - 1.0, - 1.0|
  |(- R1), 1.0, 0.0, 0.0, 0.0|
  |0.0, - 1.0, - 1.0, 0.0, 0.0|
  |0.0, 0.0, 1.0, 0.0, (- R3)|
  |0.0, 0.0, 1.0, (- R2), 0.0|
-------------------------------
Solved block of 1 variables:
Computed variable:
  uL
Solution:
  u1 + u2
-------------------------------
Solved block of 1 variables:
Computed variable:
  der(iL)
Solution:
  (- uL) / (- L)
-------------------------------
Solved block of 1 variables:
Computed variable:
  i0
Solution:
  i1 + iL
-------------------------------
")})));
  end Test1;

model Test2
 parameter Real m = 1;
 parameter Real f0 = 1;
 parameter Real f1 = 1;
 Real v;
 Real a;
 Real f;
 Real u;
 Real sa;
 Boolean startFor(start=false);
 Boolean startBack(start=false);
 Integer mode(start=2);
 Real dummy;
equation 
 der(dummy) = 1;
 u = 2*sin(time);
 m*der(v) = u - f;
 der(v) = a;
 startFor = pre(mode)==2 and sa > 1;
 startBack = pre(mode) == 2 and sa < -1;
 a = if pre(mode) == 1 or startFor then sa-1 else 
     if pre(mode) == 3 or startBack then 
     sa + 1 else 0;
 f = if pre(mode) == 1 or startFor then 
     f0 + f1*v else 
     if pre(mode) == 3 or startBack then 
     -f0 + f1*v else f0*sa;
 mode=if (pre(mode) == 1 or startFor)
      and v>0 then 1 else 
      if (pre(mode) == 3 or startBack)
          and v<0 then 3 else 2;


    annotation(__JModelica(UnitTesting(tests={
        FClassMethodTestCase(
            name="Test2",
            description="Test tearing of mixed linear equation block",
            equation_sorting=true,
            automatic_tearing=true,
            methodName="printDAEBLT",
            methodResult="
-------------------------------
Solved block of 1 variables:
Computed variable:
  der(dummy)
Solution:
  1
-------------------------------
Solved block of 1 variables:
Computed variable:
  u
Solution:
  2 * sin(time)
-------------------------------
Torn mixed linear block of 1 iteration variables and 5 solved variables:
Coefficient variability: Discrete
Solved variables:
  a
  der(v)
  f
Iteration variables:
  sa
Solved discrete variables:
  startBack
  startFor
Solved equations:
  a = if pre(mode) == 1 or startFor then sa - 1 elseif pre(mode) == 3 or startBack then sa + 1 else 0
  der(v) = a
  f = if pre(mode) == 1 or startFor then f0 + f1 * v elseif pre(mode) == 3 or startBack then - f0 + f1 * v else f0 * sa
Residual equations:
 Iteration variables: sa
  m * der(v) = u - f
Discrete equations:
  startBack = pre(mode) == 2 and sa < -1
  startFor = pre(mode) == 2 and sa > 1
Jacobian:
  |1.0, 0.0, 0.0, - (if pre(mode) == 1 or startFor then 1.0 elseif pre(mode) == 3 or startBack then 1.0 else 0)|
  |- 1.0, 1.0, 0.0, 0.0|
  |0.0, 0.0, 1.0, - (if pre(mode) == 1 or startFor then 0.0 elseif pre(mode) == 3 or startBack then 0.0 else f0)|
  |0.0, m, 1.0, 0.0|
-------------------------------
Solved block of 1 variables:
Computed variable:
  mode
Solution:
  if (pre(mode) == 1 or startFor) and v > 0 then 1 elseif (pre(mode) == 3 or startBack) and v < 0 then 3 else 2
-------------------------------
")})));
end Test2;

model WarningTest1
	Real u0,u1,u2,u3,uL;
	Real i0,i1,i2,i3,iL;
	parameter Real R1 = 1;
	parameter Real R2 = 1;
	parameter Real R3 = 1;
	parameter Real L = 1;
equation
	u0 = sin(time);
	u1 = R1*i1;
	u2 = R2*abs(i2);
	u3 = R3*i3;
	uL = L*der(iL);
	u0 = u1 + u3;
	uL = u1 + u2;
	u2 = u3;
	i0 = i1 + iL;
	i1 = i2 + i3;

	annotation(__JModelica(UnitTesting(tests={ 
		WarningTestCase(
			name="WarningTest1",
			description="Test missing start value warning",
			equation_sorting=true,
			automatic_tearing=true,
			errorMessage="
2 errors found:
Warning: in file 'Compiler/ModelicaFrontEnd/src/test/modelica/TearingTests.mo':
At line 0, column 0:
  Iteration variable \"i2\" is missing start value!
Warning: in file 'Compiler/ModelicaFrontEnd/src/test/modelica/TearingTests.mo':
At line 0, column 0:
  Iteration variable \"i3\" is missing start value!
")})));
end WarningTest1;

model WarningTest2
	Real u0,u1,u2,u3,uL;
	Real i0,i1,i2(start=1),i3,iL;
	parameter Real R1 = 1;
	parameter Real R2 = 1;
	parameter Real R3 = 1;
	parameter Real L = 1;
equation
	u0 = sin(time);
	u1 = R1*i1;
	u2 = R2*abs(i2);
	u3 = R3*i3;
	uL = L*der(iL);
	u0 = u1 + u3;
	uL = u1 + u2;
	u2 = u3;
	i0 = i1 + iL;
	i1 = i2 + i3;
	
	annotation(__JModelica(UnitTesting(tests={ 
		WarningTestCase(
			name="WarningTest2",
			description="Test missing start value warning",
			equation_sorting=true,
			automatic_tearing=true,
			errorMessage="
1 errors found:
Warning: in file 'Compiler/ModelicaFrontEnd/src/test/modelica/TearingTests.mo':
At line 0, column 0:
  Iteration variable \"i3\" is missing start value!
")})));
end WarningTest2;

model ErrorTest1
	Real u0,u1,uL;
	Real u2 annotation(__Modelon(IterationVariable));
	Real u3 annotation(__Modelon(IterationVariable));
	Real i0,i1,i2(start=1),i3,iL;
	parameter Real R1 = 1;
	parameter Real R2 = 1;
	parameter Real R3 = 1;
	parameter Real L = 1;
equation
	u0 = sin(time);
	u1 = R1*i1;
	u2 = R2*i2;
	u3 = R3*i3;
	uL = L*der(iL);
	u0 = u1 + u3 annotation(__Modelon(ResidualEquation));
	uL = u1 + u2;
	u2 = u3;
	i0 = i1 + iL;
	i1 = i2 + i3;
	
	annotation(__JModelica(UnitTesting(tests={
		ErrorTestCase(
			name="ErrorTest1",
			description="Test for alias eliminated hand guided tearing variable error",
			equation_sorting=true,
			automatic_tearing=true,
			hand_guided_tearing=true,
			errorMessage="
1 errors found:

Error: in file '...':
Semantic error at line 0, column 0:
  Hand guided tearing variable 'u3' has been alias eliminated. Selected model variable is:
    Real u2 annotation(__Modelon(IterationVariable(enabled=true)))
")})));
end ErrorTest1;

model ErrorTest2
    Real u0,u1,uL;
    Real u2 annotation(__Modelon(IterationVariable));
    Real u3 annotation(__Modelon(IterationVariable));
    Real i0,i1,i2(start=1),i3,iL;
    parameter Real R1 = 1;
    parameter Real R2 = 1;
    parameter Real R3 = 1;
    parameter Real L = 1;
equation
    u0 = sin(time);
    u1 = R1*i1;
    u2 = R2*i2;
    u3 = R3*i3;
    uL = L*der(iL);
    u0 = u1 + u3 annotation(__Modelon(ResidualEquation));
    uL = u1 + u2;
    u2 = u3;
    i0 = i1 + iL;
    i1 = i2 + i3;

    annotation(__JModelica(UnitTesting(tests={ 
        ErrorTestCase(
            name="ErrorTest2",
            description="Test so that no warning is given for linear torn blocks when no start value is set",
            equation_sorting=true,
            automatic_tearing=true,
            hand_guided_tearing=true,
            errorMessage="
1 warnings found:

Error: in file '...':
Semantic error at line 0, column 0:
  Hand guided tearing variable 'u3' has been alias eliminated. Selected model variable is:
    Real u2 annotation(__Modelon(IterationVariable(enabled=true)))
")})));
end ErrorTest2;

model BLTError1
    Integer i, j;
    Real r,s;
equation
    i = j + integer(time) + integer(s);
    i * j = 0;
    r = i * time;
    s = r * 3.14;

    annotation(__JModelica(UnitTesting(tests={
        ComplianceErrorTestCase(
            name="BLTError1",
            description="Test error message given by BLT when non-real equation contains a loop",
            errorMessage="
1 errors found:

Error: in file 'Compiler/ModelicaFrontEnd/src/test/TearingTests.mo':
Semantic error at line 0, column 0:
  Non-real equation used as residual:
i * j = 0
")})));
end BLTError1;


model RecordTearingTest1
  record R
    Real x;
    Real y;
  end R;
  function F
    input Real a;
    input Real b;
    output R r;
  algorithm
    r := R(a + b, a - b);
  end F;
  Real x, y;
  R r;
equation
  x = 1;
  y = x + 2;
  r = F(x, y);

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="RecordTearingTest1",
			methodName="printDAEBLT",
			equation_sorting=true,
			variability_propagation=false,
			inline_functions="none",
			automatic_tearing=true,
			description="Test of record tearing",
			methodResult="
-------------------------------
Solved block of 1 variables:
Computed variable:
  x
Solution:
  1
-------------------------------
Solved block of 1 variables:
Computed variable:
  y
Solution:
  x + 2
-------------------------------
Solved block of 2 variables:
Unknown variables:
  r.x
  r.y
Equations:
  (TearingTests.RecordTearingTest1.R(r.x, r.y)) = TearingTests.RecordTearingTest1.F(x, y)
-------------------------------
      ")})));
end RecordTearingTest1;

model RecordTearingTest2
  record R
    Real x;
    Real y;
  end R;
  function F
    input Real a;
    input Real b;
    output R r;
  algorithm
    r := R(a + b, a - b);
  end F;
  Real x,y;
  R r;
equation
  y = sin(time);
  r.y = 2;
  r = F(x,y);

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="RecordTearingTest2",
			description="Test of record tearing",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			methodName="printDAEBLT",
			methodResult="
-------------------------------
Solved block of 1 variables:
Computed variable:
  y
Solution:
  sin(time)
-------------------------------
Torn block of 1 iteration variables and 1 solved variables:
Solved variables:
  r.x
Iteration variables:
  x()
Solved equations:
  (TearingTests.RecordTearingTest2.R(r.x, r.y)) = TearingTests.RecordTearingTest2.F(x, y)
Residual equations:
 Iteration variables: x
  (TearingTests.RecordTearingTest2.R(r.x, r.y)) = TearingTests.RecordTearingTest2.F(x, y)
-------------------------------
")})));
end RecordTearingTest2;

model RecordTearingTest3
  function F
    input Real a;
    input Real b;
    output Real x;
    output Real y;
  algorithm
    x := a + b;
    y := a - b;
  end F;
  Real x, y,z;
equation
  y = z + 3.14;
  (x, y) = F(z, x);

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="RecordTearingTest3",
			methodName="printDAEBLT",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			description="Test of record tearing",
			methodResult="
-------------------------------
Torn block of 2 iteration variables and 1 solved variables:
Solved variables:
  y
Iteration variables:
  z()
  x()
Solved equations:
  (x, y) = TearingTests.RecordTearingTest3.F(z, x)
Residual equations:
 Iteration variables: z
  y = z + 3.14
 Iteration variables: x
  (x, y) = TearingTests.RecordTearingTest3.F(z, x)
-------------------------------
")})));
end RecordTearingTest3;

model RecordTearingTest4
  function F
    input Real a;
    input Real b;
    output Real x;
    output Real y;
  algorithm
    x := a + b;
    y := a - b;
  end F;
  Real x, y;
  Real v;
equation
   (x, y) = F(v, v);
   v = x + y;

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="RecordTearingTest4",
			methodName="printDAEBLT",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			description="Test of record tearing",
			methodResult="
-------------------------------
Torn block of 1 iteration variables and 2 solved variables:
Solved variables:
  x
  y
Iteration variables:
  v()
Solved equations:
  (x, y) = TearingTests.RecordTearingTest4.F(v, v)
  (x, y) = TearingTests.RecordTearingTest4.F(v, v)
Residual equations:
 Iteration variables: v
  v = x + y
-------------------------------
      ")})));
end RecordTearingTest4;

model RecordTearingTest5
  function F
    input Real a;
    input Real b;
    output Real x;
    output Real y;
  algorithm
    x := a + b;
    y := a - b;
  end F;
  Real a;
  Real b;
  Real c;
  Real d;
  Real e;
  Real f;
equation
  (c,d) = F(a,b);
  (e,f) = F(c,d);
  (a,b) = F(e,f);

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="RecordTearingTest5",
			methodName="printDAEBLT",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			description="Test of record tearing",
			methodResult="
-------------------------------
Torn block of 3 iteration variables and 3 solved variables:
Solved variables:
  c
  d
  e
Iteration variables:
  f()
  a()
  b()
Solved equations:
  (c, d) = TearingTests.RecordTearingTest5.F(a, b)
  (c, d) = TearingTests.RecordTearingTest5.F(a, b)
  (e, f) = TearingTests.RecordTearingTest5.F(c, d)
Residual equations:
 Iteration variables: f
  (e, f) = TearingTests.RecordTearingTest5.F(c, d)
 Iteration variables: a
  (a, b) = TearingTests.RecordTearingTest5.F(e, f)
 Iteration variables: b
  (a, b) = TearingTests.RecordTearingTest5.F(e, f)
-------------------------------
")})));
end RecordTearingTest5;

model AlgorithmTearingTest1
  Real x, y, z;
algorithm
  x := x + y + z;
  y := y - x + z;
equation
  z = x + y;

	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="AlgorithmTearingTest1",
			methodName="printDAEBLT",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			description="Test of algorithm tearing",
			methodResult="
-------------------------------
Torn block of 1 iteration variables and 2 solved variables:
Solved variables:
  y
  x
Iteration variables:
  z()
Solved equations:
  algorithm
 x := x + y + z;
 y := y - x + z;

  algorithm
 x := x + y + z;
 y := y - x + z;

Residual equations:
 Iteration variables: z
  z = x + y
-------------------------------
      ")})));
end AlgorithmTearingTest1;

model AlgorithmTearingTest2
  Real x, y, z;
algorithm
  y := y * z + 1;
equation
  x = 2*z + y;
  z = 2*x;
  
	annotation(__JModelica(UnitTesting(tests={
		FClassMethodTestCase(
			name="AlgorithmTearingTest2",
			methodName="printDAEBLT",
			equation_sorting=true,
			automatic_tearing=true,
			inline_functions="none",
			description="Test of algorithm tearing",
			methodResult="
-------------------------------
Torn block of 1 iteration variables and 2 solved variables:
Solved variables:
  y
  x
Iteration variables:
  z()
Solved equations:
  algorithm
 y := y * z + 1;

  x = 2 * z + y
Residual equations:
 Iteration variables: z
  z = 2 * x
-------------------------------
      ")})));
end AlgorithmTearingTest2;

model TearingFixedFalse1
    parameter Real a(fixed = false);
    parameter Real b(fixed = false);
    parameter Real c(fixed = false);
initial equation
    20 = c * a;
    23 = c * b;
    c = a + b;

    annotation(__JModelica(UnitTesting(tests={
        FClassMethodTestCase(
            name="TearingFixedFalse1",
            methodName="printDAEInitBLT",
            methodResult="
-------------------------------
Torn block of 2 iteration variables and 1 solved variables:
Solved variables:
  c
Iteration variables:
  a()
  b()
Solved equations:
  c = a + b
Residual equations:
 Iteration variables: a
  23 = c * b
 Iteration variables: b
  20 = c * a
-------------------------------
")})));
end TearingFixedFalse1;

end TearingTests;